﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using WarriorRush.GameDynamics;
using WarriorRush.GameDynamics.Characters;
using WarriorRush.UserInterface;
using WarriorRush.GameDynamics.Utilities;

using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;

namespace WarriorRush
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager _graphics;
        SpriteBatch _spriteBatch;
        TextureManager textureManager;
        BattleManager battleManager;
        SelectionManager Selections;
        DescriptionManager directionManager;
        AiManager aiManager;
        
        //SelectionType CurrentSelection;

        SetupManager SetupManager;
       
        //CharacterClass Rusher;
        //CharacterClass RushTarget;
        bool WaitingOnSelection;
        bool ActionInProgress;
        Player? AiPlayer;
        Rectangle ButtonPosition;
        //Player CurrentPlayer;
     
        WarriorCodex CharacterSetup;
        FrameState frameState;
        BattleState battleState;
        bool RequireAdditionalTargets;

        ArenaSquare CurrentSquare;
      

        public Game1()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "CharacterSprites";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            battleManager = new BattleManager();
            
            CharacterSetup = new WarriorCodex();
            ButtonPosition = new Rectangle(550, 400,300,300);
            WaitingOnSelection = true;
            Selections = new SelectionManager();
            TouchPanel.EnabledGestures = GestureType.Tap;

            SetupManager = new SetupManager(battleManager.Arena, CharacterSetup);
            Selections.AddSelectionOptions(Player.one, SelectionType.Setup, SetupManager.GetCurrentSquares());
            Selections.AddSelectionOptions(Player.one, SelectionType.Rusher, SetupManager.GetAttackRows(Player.one));
            Selections.AddSelectionOptions(Player.two, SelectionType.Rusher, SetupManager.GetAttackRows(Player.two));
            frameState = battleManager.FrameState;
            battleState = battleManager.BattleState;
            aiManager = new AiManager(battleState, frameState, 60);
            base.Initialize();
            AiPlayer = Player.two;
            battleState.CurrentPhase = Phases.ArenaSetup;
            battleState.CurrentPlayer = Player.one;
            battleState.CurrentSelection = SelectionType.Setup;
            RequireAdditionalTargets = false;
            battleManager.Init(CharacterSetup, Selections,SetupManager);
           
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);
            var characterFolder = "";
            textureManager = new TextureManager(Content,
                new Dictionary<CharacterTypes, String>
                    {
                        {CharacterTypes.Archer,  characterFolder +"archer"},
                        {CharacterTypes.Barbarian, characterFolder +"berzerker"},
                        {CharacterTypes.Brigand, characterFolder +"thief"},
                        {CharacterTypes.Medic, characterFolder +"medic"},
                        {CharacterTypes.Infantry,characterFolder +"infantry"},
                        {CharacterTypes.Commander, characterFolder + "commander"},
                        {CharacterTypes.Gargoyle, characterFolder+ "gargoyle"},
                        {CharacterTypes.Plaguer, characterFolder + "plaguer"}
                    },
                    new Point(64, 64),
                    new Dictionary<HighlightType, String>
                    {
                        {HighlightType.Selectable, "YellowBubble"},
                        {HighlightType.Selected, "GreenBubble"},
                        {HighlightType.Targetable,"YellowBubble"},
                        {HighlightType.Targeted,"RedBubble"}
                    }
                );

            directionManager = new DescriptionManager(textureManager);

            textureManager.SetFonts(
                Content, 
                new Dictionary<int, string> { { 1, "SmallMenuFont" }, { 2, "MediumMenuFont" }, { 3, "LargeMenuFont" } }
                );
            textureManager.GetEffectTexture(Content, "Icons");
            textureManager.GetDoneButton(Content, "done");
            textureManager.EffectTextureLocations = new Dictionary<EffectType, Point>{
                {EffectType.Blinded,    new Point(8,1)},
                {EffectType.Enraged,    new Point(7,2)},
                {EffectType.Poisoned ,  new Point(2,8)},
                {EffectType.Shielded,   new Point(7,8)},
                {EffectType.Silenced, new Point(9,3)},
                {EffectType.Dazed, new Point(8,8)},
                {EffectType.Haste, new Point(4,9)}
            };
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // TODO: Add your update logic here

            base.Update(gameTime);
            var tapPoint  = new Point();
            battleManager.Start();

            if (WaitingOnSelection)
            {
                while (TouchPanel.IsGestureAvailable)
                {
                    GestureSample gesture = TouchPanel.ReadGesture();
                    if (gesture.GestureType == GestureType.Tap)
                    {
                        tapPoint.X = (int)gesture.Position.X;
                        tapPoint.Y = (int)gesture.Position.Y;

                        frameState.IsTapped = true;
                    }
                }
                if (frameState.IsTapped || battleState.CurrentPlayer == AiPlayer)
                {
                    if (AiPlayer != battleState.CurrentPlayer || battleState.CurrentPhase == Phases.ArenaSetup)
                    {
                        frameState.IsMainTargetChosen = Selections.GetCurrentSelections(battleState.CurrentPlayer, battleState.CurrentSelection).HandleSelection(tapPoint);
                        if (rushTargetRequired())
                            frameState.IsSecondaryTargetChosen = Selections.GetCurrentSelections(battleState.CurrentPlayer, SelectionType.RushTarget).HandleSelection(tapPoint);
                    }
                    else
                    {
                        if (rushTargetRequired())
                        {
                            frameState.IsSecondaryTargetChosen = aiManager.HandleSelection(Selections.GetCurrentSelections(battleState.CurrentPlayer, SelectionType.RushTarget));
                        }
                        else
                        {
                            frameState.IsMainTargetChosen = aiManager.HandleSelection(Selections.GetCurrentSelections(battleState.CurrentPlayer, battleState.CurrentSelection));
                        }
                    }

                    if (frameState.IsSecondaryTargetChosen)
                    {
                        var secondarySelection = Selections.GetCurrentSelections(battleState.CurrentPlayer, SelectionType.RushTarget).GetSelectedSquares();

                        directionManager.CurrentWarrior = secondarySelection.FirstOrDefault(f => f.HasWarrior).Character;
                    }
                    else
                    if (frameState.IsMainTargetChosen)
                    {
                        var selectedSquares = Selections.GetCurrentSelections(battleState.CurrentPlayer, battleState.CurrentSelection).GetSelectedSquares();
                    
                        directionManager.CurrentWarrior = selectedSquares.FirstOrDefault(f => f.HasWarrior).Character;

                    }

                    if (battleState.CurrentPhase == Phases.ArenaSetup && battleState.CurrentSquare != null)
                    {
                        var itemsTapped = SetupManager.CharacterOptions.Where(f => f.Value.Contains(tapPoint));

                        if (itemsTapped.Any())
                        {
                            battleState.CurrentSquare.Character = CharacterSetup.GetCharacter(itemsTapped.First().Key);
                            directionManager.CurrentWarrior = battleState.CurrentSquare.Character;

                        } 
                        
                    }
                    

                    if (ButtonPosition.Contains(tapPoint)  )
                    {
                        frameState.IsDoneHit = true;
                    }
                    battleManager.Update();
                }
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            _spriteBatch.Begin();
            if (battleState.CurrentPhase == Phases.ArenaSetup)
            {
                DrawCharacterSelection();
                DrawSelectables(Selections.GetCurrentSelections(battleState.CurrentPlayer, SelectionType.Setup));
                textureManager.DrawDownButton(_spriteBatch, ButtonPosition);
            }
            else if (battleState.CurrentPhase == Phases.RushSelection)
            {
                DrawSelectables(Selections.GetCurrentSelections(battleState.CurrentPlayer, battleState.CurrentSelection));
                if (battleState.CurrentSelection == SelectionType.Rusher && battleState.Rusher != null)
                {
                    DrawSelectables(Selections.GetCurrentSelections(battleState.CurrentPlayer, SelectionType.RushTarget));
                    textureManager.DrawDownButton(_spriteBatch, ButtonPosition);
                }
            }
            directionManager.DrawCurrentWarrior(_spriteBatch);    
            DrawSquares();
            if (WaitingOnSelection)
            {
                textureManager.DrawDownButton(_spriteBatch, ButtonPosition);
            }

            // TODO: Add your drawing code here
            _spriteBatch.End();
            base.Draw(gameTime);
        }

        private void DrawSquares()
        {
            var currentRow = 0;
          
            foreach (var row in battleManager.Arena.Squares)
            {
                foreach (var square in row)
                {

                    DrawSquare(square);
                }
                currentRow++;
            }

        }

        private void DrawSquare(ArenaSquare square)
        {
          
            if (square.Character != null)
                DrawCharacter(square.Character,square.Position);
        }


        private void DrawCharacter(CharacterClass character, Vector2 position)
        {
            textureManager.DrawCharacter(_spriteBatch, character.Type, position);
            textureManager.DrawText(_spriteBatch, GetHealthDrawPosition(position), character.Stats.Health.ToString(),3,new Color(255, 0, 0));
            if (character.Boost != null)
                textureManager.DrawEffect(_spriteBatch, character.Boost.Type, GetBoostPosition(position));
            if (character.Drain != null)
                textureManager.DrawEffect(_spriteBatch, character.Drain.Type, GetDrainPosition(position));
        }

        private void DrawSelectables(SelectionHandler selections)
        {
            if (selections == null)
                return;
                foreach (var square in selections.Squares)
                {
                    var type = selections.SelectType;
                    if (type == HighlightType.Selectable && square.IsSelected)
                        type = HighlightType.Selected;
                    else if (type == HighlightType.Targetable && square.IsSelected)
                        type = HighlightType.Targeted;
                    textureManager.DrawSelectable(_spriteBatch, type, square.Square.Position);
                }
            
        }

        private Vector2 GetHealthDrawPosition(Vector2 CharacterPosition)
        {
            var lowerRight = textureManager.CharacterScaling * 64  - 50 ;
            return new Vector2(lowerRight + CharacterPosition.X, lowerRight + CharacterPosition.Y);
        }

        private Vector2 GetBoostPosition(Vector2 CharacterPosition)
        {
            var upperLeft = 5;
            return new Vector2(upperLeft + CharacterPosition.X, upperLeft + CharacterPosition.Y);
        }

        private Vector2 GetDrainPosition(Vector2 CharacterPosition)
        {
            var up = 5;
            var right = textureManager.CharacterScaling * 64 - 28;
            return new Vector2(right + CharacterPosition.X, up + CharacterPosition.Y);
        }

        private void DrawCharacterSelection()
        {
            foreach (var character in SetupManager.CharacterOptions)
            {
                textureManager.DrawCharacter(_spriteBatch,character.Key, new Vector2(character.Value.X, character.Value.Y));
            }
        }

        private bool rushTargetRequired()
        {
            return battleState.CurrentPhase == Phases.RushSelection && battleState.Rusher != null && battleState.CurrentSelection == SelectionType.Rusher;
        }

    }
}
